// Tencent is pleased to support the open source community by making Mars available.
// Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.

// Licensed under the MIT License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://opensource.org/licenses/MIT

// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions and
// limitations under the License.

//============================================================================
// Name        : has_member.h
// Author      :
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#ifndef COMM_HAS_MEMBER_H_
#define COMM_HAS_MEMBER_H_

template <bool TYPE>
struct bool_type {};

#define DEFINE_HAS_MEMBER_WITH_TYPE(member_name, member_type)               \
    template <typename T>                                                   \
    class has_##member_name {                                               \
     private:                                                               \
        struct yes_type {                                                   \
            char x[1];                                                      \
        };                                                                  \
        struct no_type {                                                    \
            char x[2];                                                      \
        };                                                                  \
        template <member_type(T::*)>                                        \
        struct tester;                                                      \
        template <typename U>                                               \
        static yes_type test(tester<&U::member_name>*);                     \
        template <typename U>                                               \
        static no_type test(...);                                           \
                                                                            \
     public:                                                                \
        static const bool value = (sizeof(test<T>(0)) == sizeof(yes_type)); \
    };

#define DEFINE_HAS_MEMBER(member_name)                                      \
    template <typename T>                                                   \
    class has_##member_name {                                               \
     private:                                                               \
        struct yes_type {                                                   \
            char x[1];                                                      \
        };                                                                  \
        struct no_type {                                                    \
            char x[2];                                                      \
        };                                                                  \
        template <int>                                                      \
        struct tester;                                                      \
        template <typename U>                                               \
        static yes_type test(tester<sizeof(&U::member_name)>*);             \
        template <typename U>                                               \
        static no_type test(...);                                           \
                                                                            \
     public:                                                                \
        static const bool value = (sizeof(test<T>(0)) == sizeof(yes_type)); \
    };

#endif
